package com.lambkit.util;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author yangyong(孤竹行)
 */
public class FileKit {

    public static boolean deleteQuietly(final File file) {
        if (file == null) {
            return false;
        }
        try {
            if (file.isDirectory()) {
                cleanDirectory(file);
            }
        } catch (final Exception ignored) {
        }

        try {
            return file.delete();
        } catch (final Exception ignored) {
            return false;
        }
    }

    public static void cleanDirectory(final File directory) throws IOException {
        final File[] files = verifiedListFiles(directory);

        IOException exception = null;
        for (final File file : files) {
            try {
                forceDelete(file);
            } catch (final IOException ioe) {
                exception = ioe;
            }
        }

        if (null != exception) {
            throw exception;
        }
    }

    private static File[] verifiedListFiles(final File directory) throws IOException {
        if (!directory.exists()) {
            final String message = directory + " does not exist";
            throw new IllegalArgumentException(message);
        }

        if (!directory.isDirectory()) {
            final String message = directory + " is not a directory";
            throw new IllegalArgumentException(message);
        }

        final File[] files = directory.listFiles();
        if (files == null) { // null if security restricted
            throw new IOException("Failed to list contents of " + directory);
        }
        return files;
    }

    public static void forceDelete(final File file) throws IOException {
        if (file.isDirectory()) {
            deleteDirectory(file);
        } else {
            final boolean filePresent = file.exists();
            if (!file.delete()) {
                if (!filePresent) {
                    throw new FileNotFoundException("File does not exist: " + file);
                }
                final String message = "Unable to delete file: " + file;
                throw new IOException(message);
            }
        }
    }

    public static void deleteDirectory(final File directory) throws IOException {
        if (!directory.exists()) {
            return;
        }

        if (!isSymlink(directory)) {
            cleanDirectory(directory);
        }

        if (!directory.delete()) {
            final String message = "Unable to delete directory " + directory + ".";
            throw new IOException(message);
        }
    }

    public static boolean isSymlink(final File file) throws IOException {
        if (file == null) {
            throw new NullPointerException("File must not be null");
        }
        return Files.isSymbolicLink(file.toPath());
    }

    ////////////////////////////////////////////////////////
    // FileKit

    /**
     * 删除目录
     * @param dir
     * @throws IOException
     */
    public static void cleanDirectory(String dir) throws IOException {
        if(dir==null || dir.length() < 1) {
            return;
        }
        File file = new File(dir);
        cleanDirectory(file);
        Printer.print(FileKit.class, "resource", "清空目录[clean dir]：" + file.getAbsolutePath());
    }

    /**
     * 删除目录
     * @param dir
     * @throws IOException
     */
    public static void deleteOutRootDir(String dir) throws IOException {
        if(dir==null || dir.length() < 1) {
            return;
        }
        File file = new File(dir);
        deleteDirectory(file);
        System.out.println("删除目录[delete dir]：" + file.getAbsolutePath());
    }

    /**
     * 创建输出目录
     */
    public static void createOutRootDir(Map<String, Object> templateModel, Map<String, Object> filepathModel) {
        if(filepathModel==null) {
            return;
        }
        @SuppressWarnings("unchecked")
        List<String> folderList = (List<String>) filepathModel.get("folderList");
        if(folderList==null) {
            return;
        }
        String folderpath = (String) filepathModel.get("folderpath");
        // 开始处理
        for (String dir : folderList) {
            // 处理文件夹地址模板
            String newPath = processDir(templateModel, dir);
            if(newPath==null) {
                continue;
            }
            String newdir = newPath.replace(replacePath(folderpath),
                    (String) templateModel.get("outRootDir"));
            File filePath = new File(newdir);
            createFilePath(filePath);
        }
    }

    /**
     * 创建文件地址模型
     * @param templatePath
     */
    public static Map<String, Object> createFilepathModel(String templateFolder, String templatePath) {
//        boolean flag = templatePath.length() > 2 && ":".equals(templatePath.substring(1, 2)) ? false : true;
//        // 模板文件夹位置
//        String folderpath = flag ? System.getProperty("user.dir") + templatePath : templatePath;
        String folderpath = templateFolder + templatePath;
        folderpath = replacePath(folderpath);
        //System.out.println("模板所在文件夹绝对路径为: " + folderpath);
        // 遍历文件夹template
        List<String> fileList = new ArrayList<String>();
        List<String> folderList = new ArrayList<String>();
        File file = new File(folderpath);
        getDirectory(file, fileList, folderList);
        Map<String, Object> filepathModel = new HashMap<String, Object>();
        filepathModel.put("filelist", fileList);
        filepathModel.put("folderList", folderList);
        filepathModel.put("folderpath", folderpath);
        filepathModel.put("templatePath", templatePath);
        return filepathModel;
    }

    /**
     * 创建文件
     *
     * @param file
     */
    public static void createFilePath(File file) {
        if (!file.exists()) {
            System.out.println("创建[" + file.getAbsolutePath() + "]情况：" + file.mkdirs());
        } else {
            //System.out.println("存在目录：" + file.getAbsolutePath());
        }
    }

    public static void createDirectory(String path) {
        File file = new File(path);
        // 如果文件夹不存在则创建
        if (!file.exists() && !file.isDirectory()) {
            //System.out.println("//不存在");
            file.mkdir();
        } else {
            //System.out.println("//目录存在");
        }
    }

    /**
     * 判断并创建父类目录
     * @param file
     */
    public static void checkAndCreateParent(File file) {
        if (!file.getParentFile().isDirectory()) {
            file.getParentFile().mkdirs();
        }
    }

    /**
     * 递归遍历文件及文件夹
     *
     * @param file
     * @param filelist
     * @param folderlist
     */
    public static void getDirectory(File file, List<String> filelist,
                                    List<String> folderlist) {
        File flist[] = file.listFiles();
        if (flist == null || flist.length == 0) {
            return;
        }
        for (File f : flist) {
            if (f.isDirectory()) {
                // 这里将列出所有的文件夹
                // 绝对路径f.getAbsolutePath()
                // 文件名f.getName()
                folderlist.add(f.getAbsolutePath());
                getDirectory(f, filelist, folderlist);
            } else {
                // 这里将列出所有的文件
                if(!f.getName().endsWith(".include")) {
                    filelist.add(f.getAbsolutePath());
                }
            }
        }
    }

    /**
     * 替换文件地址中的模板
     * 比如：src/${basepackage_dir}/service 替换为 src/com/app/service
     * 其中：basepackage_dir=com/app
     * @return
     */
    public static String processDir(Map<String, Object> templateModel, String path) {
        String result_dir = "";
        // 替换反斜杠"\",使用"\\\\",替换为"/"
        String dir = replacePath(path);
        // 正则表达式,识别${*}字符串
        String regEx2 = "\\$\\{(.[^/]*)\\}";
        // 正则表达式,识别#(*)字符串
        String regEx1 = "\\#\\((.[^/]*)\\)";
        // 拆分地址
        String[] array = dir.split("/");
        for (int i = 0; i < array.length; i++) {
            //System.out.print(array[i]+"; ");
            if (i != 0) {
                result_dir += "/";
            }
            Pattern pattern = Pattern.compile(regEx2);
            Matcher matcher = pattern.matcher(array[i]);
            if (matcher.find()) {
                // 取大括号{}中的字符
                //System.out.print(matcher.group(1)+"; "+i);
                String val = String.valueOf(templateModel.get(matcher.group(1)));
                if("null".equals(val)) {
                    return null;
                }
                String res = matcher.replaceAll(val);
                result_dir += val != null ? res : matcher.group(1);
            } else {
                Pattern pattern1 = Pattern.compile(regEx1);
                Matcher matcher1 = pattern1.matcher(array[i]);
                if (matcher1.find()) {
                    // 取大括号{}中的字符
                    //System.out.print(matcher.group(1)+"; "+i);
                    String val = String.valueOf(templateModel.get(matcher1.group(1)));
                    if("null".equals(val)) {
                        return null;
                    }
                    String res = matcher1.replaceAll(val);
                    result_dir += val != null ? res : matcher1.group(1);
                } else {
                    result_dir += array[i];
                }
            }
            // System.out.println();
        }
        return result_dir;
    }

    /**
     * 替换路径中的"\"为"/" 比如："d:\web\apps"替换为"d:/web/apps"
     *
     * @param path
     * @return
     */
    public static String replacePath(String path) {
        return path.replaceAll("\\\\", "/");
    }

    /*
     * Java文件操作 获取文件扩展名
     *
     * Created on: 2011-8-2 Author: blueeagle
     */
    public static String getExtensionName(String filename) {
        if ((filename != null) && (filename.length() > 0)) {
            int dot = filename.lastIndexOf('.');
            if ((dot > -1) && (dot < (filename.length() - 1))) {
                return filename.substring(dot + 1);
            }
        }
        return filename;
    }

    /*
     * Java文件操作 获取不带扩展名的文件名
     *
     * Created on: 2011-8-2 Author: blueeagle
     */
    public static String getFileNameNoEx(String filename) {
        if ((filename != null) && (filename.length() > 0)) {
            int dot = filename.lastIndexOf('.');
            if ((dot > -1) && (dot < (filename.length()))) {
                return filename.substring(0, dot);
            }
        }
        return filename;
    }

}
